/**
 * public private protected
 * 
 * public修饰的属性或者方法是共有的
 *  可以在任何地方被访问到，默认所有的属性或者方法都是public的
 * private修饰的属性或者方法是私有的
 *  不能在声明它的类外面访问
 * protected 修饰的属性是受保护的
 *  它和private类型，但它能在子类中被访问到
 */


// 创建Person类
class Person {
  private name:string = "张三"
  protected age:number = 18
  city:string = "深圳"
  say():void {
    console.log(this.name, this.age)
  }
}

// 创建Person实例
var p = new Person()
p.say()

// private属性只能在类内部进行访问
// 报错：属性name为私有属性
// console.log(p.name)

// 报错：age受保护，只能在父类及其子类中使用
// console.log(p.age)

console.log(p.city)

// 创建Child子类
class Child extends Person {
  callParent() {
    // 父类将属性定义成私有private，子类不可以进行访问
    // 报错：name为私有属性，只能在person类里使用
    // console.log(super.name)
    // 父类的属性定义成受保护protected，子类可以进行访问
    
    // 属性用this访问
    console.log(this.age)
    //不允许在构造函数外部或在构造函数内的嵌套函数中进行 Super 调用。
    // console.log(super(age))
    // "super" 访问基类的公共方法和受保护方法
    // super.say()
  }
  fun(): any {
    console.log(this.city)
    // 报错：找不到名称city
    // console.log(city)
  }
  static test():any {
    console.log("test")
    // 静态方法里，不允许使用this
    // 报错：typeof Child上不存在属性city
    // console.log(this.city)
    // 报错；找不到名称city
    // console.log(city)
  }
}

var c = new Child()
c.callParent()
// 子类继承了父类，但不能在外部访问受保护的和私有的属性
// console.log(c.age)
// 可以访问父类公开的属性或方法
console.log(c.say)

console.log(Child.test())

// 如果出现标识符重复的错误，要加上
export {}